package top.aiprogram.attend.service;

import jdk.nashorn.internal.runtime.ECMAException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.aiprogram.attend.dao.AttendMapper;
import top.aiprogram.attend.entity.Attend;
import top.aiprogram.attend.vo.QueryCondition;
import top.aiprogram.common.page.PageQueryBean;
import top.aiprogram.common.utils.DateUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by HP on 2018/10/17.
 */
@Service("AttendServiceImpl")
public class AttendServiceImpl implements AttendService {
    private static final int HOUR_OF_NOON = 12;
    private static final int MINUTE_OF_NOON = 0;
    private static final Integer ABSENCE_DAY = 480;
    private static final Byte ATTEND_STATUS_ABNORMAL = 2;
    private static final Byte ATTEND_STATUS_NORMAL = 1;
    //记录用户签到异常,要记录哪个类的日志呢
    private Log log= LogFactory.getLog(AttendServiceImpl.class);

    @Autowired
    private AttendMapper attendMapper;
/*
@Author JackQi {www.coder520.com}
@DATE 2018/10/17 10:01
@Description:进行打卡的方法,并且捕获其中发生的异常,并记录到日志.
*/
    @Override
    @Transactional
    public void doAttend(Attend attend) {
        try{
            /*
            中午十二点之前打卡,都算早打卡,如果9,30以后,直接异常,算迟到
            十二点以后都算下午打卡
            下午打卡与上午打卡计算时间差,不足八小时,都算异常,要存进去,缺勤多长时间
            十八点之前打卡都算异常.
             */
            Date today = new Date();
            Date date = DateUtils.getDate(HOUR_OF_NOON, MINUTE_OF_NOON);
            Attend attend1=attendMapper.selectByUserId(attend.getUserId());

            if (attend1==null){
                if (today.compareTo(date)<=0){
                    attend.setAttendMorning(today);
                }else {
                    attend.setAttendEvening(today);
                }
                attendMapper.insertSelective(attend);
            }else {
                if (today.compareTo(date)<=0){
                    if (attend1.getAttendMorning()==null){
                        attend1.setAttendMorning(today);
                    }
                }else {
                    attend1.setAttendEvening(today);
                }
                int i = attendMapper.updateByPrimaryKeySelective(attend1);
            }

        }catch (Exception e){
            //将发生的错误记录到日志的哪个级别呢.
            log.error("用户签到异常",e);
            //事务中的错误必须抛出,不然事务就没有用了
            throw e;
        }

    }

    @Override
    public PageQueryBean listAttend(QueryCondition Condition) {
        //根据条件查询 count记录数目
        int count=attendMapper.countByCondition(Condition);
        PageQueryBean pageQueryBean=new PageQueryBean();
        //如果有记录 才去查询分页数据 没有相关记录数目 没必要去查分页数据

        if (count>0){
            pageQueryBean.setTotalRows(count);
            pageQueryBean.setCurrentPage(Condition.getCurrentPage());
            pageQueryBean.setPageSize(Condition.getPageSize());
           List<Attend> attendList= attendMapper.selectAttendPage(Condition);
           pageQueryBean.setItems(attendList);
        }
            return pageQueryBean;
    }

    /*
    @Author JackQi {www.coder520.com}
    @DATE 2018/10/18 20:47
    @Description:配合定时器工作的事务处理
    */

    @Transactional
    @Override
    public void checkAttend() {
        //查询缺勤用户ID 插入打卡记录  并且设置为异常 缺勤480分钟
        List<Long> userIdList =attendMapper.selectTodayAbsence();
        if(CollectionUtils.isNotEmpty(userIdList)){
            List<Attend> attendList = new ArrayList<>();
            for(Long userId:userIdList){
                Attend attend = new Attend();
                attend.setUserId(userId);
                attend.setAttendDate(new Date());
                attend.setAttendWeek((byte)DateUtils.getWeek());
                attend.setAbsence(ABSENCE_DAY);
                attend.setAttendAtatus(ATTEND_STATUS_ABNORMAL);
                attendList.add(attend);
            }
            //能批量插入,尽量批量插入,一条SQL语句就解决了,循环插入的效率太低,记住这回事,往数据库中
            //插入数据,有批量插入这一说.
            attendMapper.batchInsert(attendList);
        }
        // 检查晚打卡 将下班未打卡记录设置为异常
        List<Attend> absenceList = attendMapper.selectTodayEveningAbsence();
        //代码的健壮性体现在这些非空判断上,不然容易造成空指针,CoolectionUtils这是一个Apache提供的一个工具类
        //Apache还提供了判断字符串等是否为空的工具类,可以下去查查相关资料
        if(CollectionUtils.isNotEmpty(absenceList)){
            for(Attend attend : absenceList){
                attend.setAbsence(ABSENCE_DAY);
                attend.setAttendAtatus(ATTEND_STATUS_ABNORMAL);
                //没有批量更新这种操作,当更新的数据量大的时候,循环更新效率很低,需要想其他的方法了.更新和插入不一样,
                //插入不需要根据某个条件匹配插入,而更新每条数据都要匹配相应的主键,因此没法进行批量的更新操作.批量
                //操作适用于没有要寻找匹配条件的情况.
                attendMapper.updateByPrimaryKeySelective(attend);
            }
        }
    }
}
